home *** CD-ROM | disk | FTP | other *** search
- /*
- * $Id: dos_gen.c,v 4.19 1996/03/15 07:41:11 hubert Exp $
- *
- * Program: Operating system dependent routines - MS DOS Generic
- *
- *
- * Michael Seibel
- * Networks and Distributed Computing
- * Computing and Communications
- * University of Washington
- * Administration Builiding, AG-44
- * Seattle, Washington, 98195, USA
- * Internet: mikes@cac.washington.edu
- *
- * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
- *
- *
- * Pine and Pico are registered trademarks of the University of Washington.
- * No commercial use of these trademarks may be made without prior written
- * permission of the University of Washington.
- *
- * Pine, Pico, and Pilot software and its included text are Copyright
- * 1989-1996 by the University of Washington.
- *
- * The full text of our legal notices is contained in the file called
- * CPYRIGHT, included with this distribution.
- *
- *
- * Notes:
- * - This file should contain the cross section of functions useful
- * in both DOS and Windows ports of pico.
- *
- */
-
- #ifdef WIN32
- #include <io.h>
- #endif
-
-
- /*
- * picosigs - Install any handlers for the signals we're interested
- * in catching.
- */
- picosigs()
- {
- /* no op */
- }
-
-
- /*
- * Useful definitions...
- */
- #ifdef MOUSE
- static int mexist = 0; /* is the mouse driver installed? */
- static int nbuttons; /* number of buttons on the mouse */
- static unsigned mnoop;
- #endif
- static unsigned char okinfname[32] = {
- 0, 0, /* ^@ - ^G, ^H - ^O */
- 0, 0, /* ^P - ^W, ^X - ^_ */
- 0x80, 0x17, /* SP - ' , ( - / */
- 0xff, 0xe0, /* 0 - 7 , 8 - ? */
- 0x7f, 0xff, /* @ - G , H - O */
- 0xff, 0xe9, /* P - W , X - _ */
- 0x7f, 0xff, /* ` - g , h - o */
- 0xff, 0xf6, /* p - w , x - DEL */
- 0, 0, /* > DEL */
- 0, 0, /* > DEL */
- 0, 0, /* > DEL */
- 0, 0, /* > DEL */
- 0, 0 /* > DEL */
- };
-
-
- /*
- * fallowc - returns TRUE if c is allowable in filenames, FALSE otw
- */
- fallowc(c)
- int c;
- {
- return(okinfname[c>>3] & 0x80>>(c&7));
- }
-
-
- #ifdef MOUSE
- /*
- * end_mouse - a no-op on DOS/Windows
- */
- void
- end_mouse()
- {
- }
-
-
- /*
- * mouseexist - function to let outsiders know if mouse is turned on
- * or not.
- */
- mouseexist()
- {
- return(mexist);
- }
- #endif /* MOUSE */
-
-
- /*
- * fexist - returns TRUE if the file exists, FALSE otherwise
- */
- fexist(file, m, l)
- char *file, *m;
- long *l;
- {
- struct stat sbuf;
-
- if(l != NULL)
- *l = 0L;
-
- if(stat(file, &sbuf) < 0){
- if(errno == ENOENT) /* File not found */
- return(FIOFNF);
- else
- return(FIOERR);
- }
-
- if(l != NULL)
- *l = sbuf.st_size;
-
- if(sbuf.st_mode & S_IFDIR)
- return(FIODIR);
- else if(*m == 't') /* no links, just say yes */
- return(FIOSUC);
-
- if(m[0] == 'r') /* read access? */
- return((S_IREAD & sbuf.st_mode) ? FIOSUC : FIONRD);
- else if(m[0] == 'w') /* write access? */
- return((S_IWRITE & sbuf.st_mode) ? FIOSUC : FIONWT);
- else if(m[0] == 'x') /* execute access? */
- return((S_IEXEC & sbuf.st_mode) ? FIOSUC : FIONEX);
- return(FIOERR); /* what? */
- }
-
-
- /*
- * isdir - returns true if fn is a readable directory, false otherwise
- * silent on errors (we'll let someone else notice the problem;)).
- */
- isdir(fn, l)
- char *fn;
- long *l;
- {
- struct stat sbuf;
-
- if(l)
- *l = 0;
-
- if(stat(fn, &sbuf) < 0)
- return(0);
-
- if(l)
- *l = sbuf.st_size;
-
- return(sbuf.st_mode & S_IFDIR);
- }
-
-
- /*
- * gethomedir - returns the users home directory
- * Note: home is malloc'd for life of pico
- */
- char *gethomedir(l)
- int *l;
- {
- static char *home = NULL;
- static short hlen = 0;
-
- if(home == NULL){
- char buf[NLINE];
- sprintf(buf, "%c:\\", _getdrive() + 'A' - 1);
- hlen = strlen(buf);
- if((home=(char *)malloc(((size_t)hlen + 1) * sizeof(char))) == NULL){
- emlwrite("Problem allocating space for home dir", NULL);
- return(0);
- }
- strcpy(home, buf);
- }
-
- if(l)
- *l = hlen;
-
- return(home);
- }
-
-
- /*
- * homeless - returns true if given file does not reside in the current
- * user's home directory tree.
- */
- homeless(f)
- char *f;
- {
- char *home;
- int len;
-
- home = gethomedir(&len);
- return(strncmp(home, f, len));
- }
-
-
- /*
- * errstr - return system error string corresponding to given errno
- * Note: strerror() is not provided on all systems, so it's
- * done here once and for all.
- */
- char *errstr(err)
- int err;
- {
- return((err >= 0 && err < sys_nerr) ? sys_errlist[err] : NULL);
- }
-
-
- /*
- * getfnames - return all file names in the given directory in a single
- * malloc'd string. n contains the number of names
- */
- char *getfnames(dn, pat, n, e)
- char *dn, *pat, *e;
- int *n;
- {
- int status;
- long l;
- char *names, *np, *p;
- char buf[NLINE];
- struct stat sbuf;
- #ifdef WIN32
- struct _finddata_t dbuf;
- long findrv;
- #else
- struct find_t dbuf; /* opened directory */
- #endif
-
- *n = 0;
-
- if(stat(dn, &sbuf) < 0){
- if(e)
- sprintf(e, "\007Dir \"%s\": %s", dn, strerror(errno));
-
- return(NULL);
- }
- else{
- l = sbuf.st_size;
- if(!(sbuf.st_mode & S_IFDIR)){
- if(e)
- sprintf(e, "\007Not a directory: \"%s\"", dn);
-
- return(NULL);
- }
- }
-
- if((names=(char *)malloc(sizeof(char)*3072)) == NULL){
- if(e)
- sprintf(e, "\007Can't malloc space for file names", NULL);
-
- return(NULL);
- }
-
- np = names;
-
- strcpy(buf, dn);
- sprintf(buf, "%s%s%s*%s%s", dn,
- (dn[strlen(dn)-1] == '\\') ? "\\" : "",
- (pat && *pat) ? pat : "",
- (pat && *pat && strchr(pat, '.')) ? "" : ".",
- (pat && *pat && strchr(pat, '.')) ? "" : "*");
- #ifdef WIN32
- if((findrv = _findfirst(buf, &dbuf)) < 0){
- #else
- if(_dos_findfirst(buf, _A_NORMAL|_A_SUBDIR, &dbuf) != 0){
- #endif
- if(e)
- sprintf(e, "Can't find first file in \"%s\"", dn);
-
- free((char *) names);
- return(NULL);
- }
-
- do{
- (*n)++;
- p = dbuf.name;
- while((*np++ = *p++) != '\0')
- ;
- }
- #ifdef WIN32
- while(_findnext(findrv, &dbuf) == 0);
- _findclose(findrv);
- #else
- while(_dos_findnext(&dbuf) == 0);
- #endif
-
- return(names);
- }
-
-
- /*
- * fioperr - given the error number and file name, display error
- */
- void
- fioperr(e, f)
- int e;
- char *f;
- {
- switch(e){
- case FIOFNF: /* File not found */
- emlwrite("\007File \"%s\" not found", f);
- break;
- case FIOEOF: /* end of file */
- emlwrite("\007End of file \"%s\" reached", f);
- break;
- case FIOLNG: /* name too long */
- emlwrite("\007File name \"%s\" too long", f);
- break;
- case FIODIR: /* file is a directory */
- emlwrite("\007File \"%s\" is a directory", f);
- break;
- case FIONWT:
- emlwrite("\007Write permission denied: %s", f);
- break;
- case FIONRD:
- emlwrite("\007Read permission denied: %s", f);
- break;
- case FIONEX:
- emlwrite("\007Execute permission denied: %s", f);
- break;
- default:
- emlwrite("\007File I/O error: %s", f);
- }
- }
-
-
- /*
- * pfnexpand - pico's function to expand the given file name if there is
- * a leading '~'
- */
- char *pfnexpand(fn, len)
- char *fn;
- int len;
- {
- return(fn);
- }
-
-
- /*
- * fixpath - make the given pathname into an absolute path
- */
- fixpath(name, len)
- char *name;
- int len;
- {
- char file[_MAX_PATH];
- int dr;
-
- if(!len)
- return(0);
-
- /* return the full path of given file */
- if(isalpha(name[0]) && name[1] == ':'){ /* have drive spec? */
- if(name[2] != '\\'){ /* including path? */
- dr = toupper(name[0]) - 'A' + 1;
- if(_getdcwd(dr, file, _MAX_PATH) != NULL){
- if(file[strlen(file)-1] != '\\')
- strcat(file, "\\");
-
- strcat(file, &name[2]); /* add file name */
- }
- else
- return(0);
- }
- else
- return(1); /* fully qualified with drive and path! */
- }
- else if(name[0] == '\\') { /* no drive spec! */
- sprintf(file, "%c:%s", _getdrive()+'A'-1, name);
- }
- else{
- if(Pmaster && !gmode&MDCURDIR)
- strcpy(file, gmode&MDTREE ? opertree : gethomedir(NULL));
- else if(!_getcwd(file, _MAX_PATH)) /* no qualification */
- return(0);
-
- if(*name){ /* if name, append it */
- strcat(file, "\\");
- strcat(file, name);
- }
- }
-
- strncpy(name, file, len); /* copy back to real buffer */
- name[len-1] = '\0'; /* tie off just in case */
- return(1);
- }
-
-
- /*
- * compresspath - given a base path and an additional directory, collapse
- * ".." and "." elements and return absolute path (appending
- * base if necessary).
- *
- * returns 1 if OK,
- * 0 if there's a problem
- * new path, by side effect, if things went OK
- */
- compresspath(base, path, len)
- char *base, *path;
- int len;
- {
- register int i;
- int depth = 0;
- char *p;
- char *stack[32];
- char pathbuf[NLINE];
-
- #define PUSHD(X) (stack[depth++] = X)
- #define POPD() ((depth > 0) ? stack[--depth] : "")
-
- strcpy(pathbuf, path);
- fixpath(pathbuf, len);
-
- p = pathbuf;
- for(i=0; pathbuf[i] != '\0'; i++){ /* pass thru path name */
- if(pathbuf[i] == C_FILESEP){
- if(p != pathbuf)
- PUSHD(p); /* push dir entry */
- p = &pathbuf[i+1]; /* advance p */
- pathbuf[i] = '\0'; /* cap old p off */
- continue;
- }
-
- if(pathbuf[i] == '.'){ /* special cases! */
- if(pathbuf[i+1] == '.' /* parent */
- && (pathbuf[i+2] == C_FILESEP || pathbuf[i+2] == '\0')){
- if(!strcmp(POPD(),"")) /* bad news! */
- return(0);
-
- i += 2;
- p = (pathbuf[i] == '\0') ? "" : &pathbuf[i+1];
- }
- else if(pathbuf[i+1] == C_FILESEP || pathbuf[i+1] == '\0'){
- i++;
- p = (pathbuf[i] == '\0') ? "" : &pathbuf[i+1];
- }
- }
- }
-
- if(*p != '\0')
- PUSHD(p); /* get last element */
-
- path[0] = '\0';
- for(i = 0; i < depth; i++){
- strcat(path, S_FILESEP);
- strcat(path, stack[i]);
- }
-
- return(1); /* everything's ok */
- }
-
-
- /*
- * tmpname - return a temporary file name in the given buffer
- */
- void
- tmpname(name)
- char *name;
- {
- sprintf(name, "%s.txt", tempnam(getenv("TEMP"), "ae"));
- }
-
-
- /*
- * Take a file name, and from it
- * fabricate a buffer name. This routine knows
- * about the syntax of file names on the target system.
- * I suppose that this information could be put in
- * a better place than a line of code.
- */
- void
- makename(bname, fname)
- char bname[];
- char fname[];
- {
- register char *cp1;
- register char *cp2;
-
- cp1 = &fname[0];
- while (*cp1 != 0)
- ++cp1;
-
- while (cp1!=&fname[0] && cp1[-1]!='\\')
- --cp1;
- cp2 = &bname[0];
- while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';')
- *cp2++ = *cp1++;
- *cp2 = 0;
- }
-
-
- /*
- * copy - copy contents of file 'a' into a file named 'b'. Return error
- * if either isn't accessible or is a directory
- */
- copy(a, b)
- char *a, *b;
- {
- int in, out, n, rv = 0;
- char *cb;
- struct stat tsb, fsb;
-
- if(stat(a, &fsb) < 0){ /* get source file info */
- emlwrite("Can't Copy: %s", errstr(errno));
- return(-1);
- }
-
- if(!(fsb.st_mode&S_IREAD)){ /* can we read it? */
- emlwrite("\007Read permission denied: %s", a);
- return(-1);
- }
-
- if((fsb.st_mode&S_IFMT) == S_IFDIR){ /* is it a directory? */
- emlwrite("\007Can't copy: %s is a directory", a);
- return(-1);
- }
-
- if(stat(b, &tsb) < 0){ /* get dest file's mode */
- switch(errno){
- case ENOENT:
- break; /* these are OK */
- default:
- emlwrite("\007Can't Copy: %s", errstr(errno));
- return(-1);
- }
- }
- else{
- if(!(tsb.st_mode&S_IWRITE)){ /* can we write it? */
- emlwrite("\007Write permission denied: %s", b);
- return(-1);
- }
-
- if((tsb.st_mode&S_IFMT) == S_IFDIR){ /* is it directory? */
- emlwrite("\007Can't copy: %s is a directory", b);
- return(-1);
- }
-
- if(fsb.st_dev == tsb.st_dev && fsb.st_ino == tsb.st_ino){
- emlwrite("\007Identical files. File not copied", NULL);
- return(-1);
- }
- }
-
- if((in = open(a, _O_RDONLY)) < 0){
- emlwrite("Copy Failed: %s", errstr(errno));
- return(-1);
- }
-
- if((out=creat(b, fsb.st_mode&0xfff)) < 0){
- emlwrite("Can't Copy: %s", errstr(errno));
- close(in);
- return(-1);
- }
-
- if((cb = (char *)malloc(NLINE*sizeof(char))) == NULL){
- emlwrite("Can't allocate space for copy buffer!", NULL);
- close(in);
- close(out);
- return(-1);
- }
-
- while(1){ /* do the copy */
- if((n = read(in, cb, NLINE)) < 0){
- emlwrite("Can't Read Copy: %s", errstr(errno));
- rv = -1;
- break; /* get out now */
- }
-
- if(n == 0) /* done! */
- break;
-
- if(write(out, cb, n) != n){
- emlwrite("Can't Write Copy: %s", errstr(errno));
- rv = -1;
- break;
- }
- }
-
- free(cb);
- close(in);
- close(out);
- return(rv);
- }
-
-
- /*
- * Open a file for writing. Return TRUE if all is well, and FALSE on error
- * (cannot create).
- */
- ffwopen(fn)
- char *fn;
- {
- extern FILE *ffp;
-
- if ((ffp=fopen(fn, "w")) == NULL) {
- emlwrite("Cannot open file for writing", NULL);
- return (FIOERR);
- }
-
- return (FIOSUC);
- }
-
-
- /*
- * Close a file. Should look at the status in all systems.
- */
- ffclose()
- {
- extern FILE *ffp;
-
- if (fclose(ffp) != FALSE) {
- emlwrite("Error closing file", NULL);
- return(FIOERR);
- }
-
- return(FIOSUC);
- }
-
-
- /*
- * worthit - generic sort of test to roughly gage usefulness of using
- * optimized scrolling.
- *
- * note:
- * returns the line on the screen, l, that the dot is currently on
- */
- worthit(l)
- int *l;
- {
- int i; /* l is current line */
- unsigned below; /* below is avg # of ch/line under . */
-
- *l = doton(&i, &below);
- below = (i > 0) ? below/(unsigned)i : 0;
-
- return(below > 3);
- }
-
-
- /*
- * o_insert - optimize screen insert of char c
- */
- o_insert(c)
- char c;
- {
- return(0);
- }
-
-
- /*
- * o_delete - optimized character deletion
- */
- o_delete()
- {
- return(0);
- }
-
-
- /*
- * pico_new_mail - just checks mtime and atime of mail file and notifies user
- * if it's possible that they have new mail.
- */
- pico_new_mail()
- {
- return(0);
- }
-
-
-
- /*
- * time_to_check - checks the current time against the last time called
- * and returns true if the elapsed time is > timeout
- */
- time_to_check()
- {
- static time_t lasttime = 0L;
-
- if(!timeout)
- return(FALSE);
-
- if(time((long *) 0) - lasttime > (time_t)timeout){
- lasttime = time((long *) 0);
- return(TRUE);
- }
- else
- return(FALSE);
- }
-
-
- /*
- * sstrcasecmp - compare two pointers to strings case independently
- */
- sstrcasecmp(s1, s2)
- QcompType *s1, *s2;
- {
- return(stricmp(*(char **)s1, *(char **)s2));
- }
-
-
- /*
- * chkptinit -- initialize anything we need to support composer
- * checkpointing
- */
- chkptinit(file, n)
- char *file;
- int n;
- {
- if(!file[0]){
- long gmode_save = gmode;
-
- if(gmode&MDCURDIR)
- gmode &= ~MDCURDIR; /* so fixpath will use home dir */
-
- strcpy(file, "#picoTM0.txt");
- fixpath(file, NLINE);
- gmode = gmode_save;
- }
- else{
- int l = strlen(file);
-
- if(file[l-1] != '\\'){
- file[l++] = '\\';
- file[l] = '\0';
- }
-
- strcpy(file + l, "#picoTM0.txt");
- }
-
- if(fexist(file, "r", NULL) == FIOSUC){ /* does file exist? */
- char copy[NLINE];
-
- strcpy(copy, "#picoTM1.txt");
- fixpath(copy, NLINE);
- rename(file, copy); /* save so we don't overwrite it */
- }
-
- unlink(file);
- }
-
-
- /*
- * sleep the given number of microseconds
- */
- ssleep(s)
- clock_t s;
- {
- s += clock();
- while(s > clock())
- ;
- }
-
-
- /*
- * sleep the given number of seconds
- */
- sleep(t)
- int t;
- {
- time_t out = (time_t)t + time((long *) 0);
- while(out > time((long *) 0))
- ;
- }
-